//
//  DMLifecycleCallbackManager.m
//  DualMediationSDK
//
//  SDK回调管理器实现
//

#import "DMLifecycleCallbackManager.h"
#import "../Core/DMLifecycleDelegateRegistry.h"

#pragma mark - 回调统计信息实现

@implementation DMCallbackStatistics

- (NSTimeInterval)averageProcessTime {
    if (self.successfulCallbacks == 0) {
        return 0;
    }
    return self.totalProcessTime / self.successfulCallbacks;
}

- (NSString *)description {
    return [NSString stringWithFormat:@"<DMCallbackStatistics: total=%lu, success=%lu, failed=%lu, avgTime=%.3fms>",
            (unsigned long)self.totalCallbacks,
            (unsigned long)self.successfulCallbacks,
            (unsigned long)self.failedCallbacks,
            self.averageProcessTime * 1000];
}

@end

#pragma mark - 回调日志项

@interface DMCallbackLogItem : NSObject
@property (nonatomic, strong) NSString *callbackType;
@property (nonatomic, strong) NSDate *timestamp;
@property (nonatomic, assign) DMCallbackHandleResult result;
@property (nonatomic, assign) NSTimeInterval duration;
@property (nonatomic, assign) NSUInteger handlerCount;
@property (nonatomic, strong, nullable) NSString *errorDescription;
@property (nonatomic, strong, nullable) id data;
@end

@implementation DMCallbackLogItem
@end

#pragma mark - 待处理回调项

@interface DMPendingCallback : NSObject
@property (nonatomic, strong) NSString *callbackType;
@property (nonatomic, strong, nullable) id data;
@property (nonatomic, strong) NSDate *timestamp;
@property (nonatomic, copy, nullable) void(^completion)(DMCallbackHandleResult result);
@end

@implementation DMPendingCallback
@end

#pragma mark - 回调管理器实现

@interface DMLifecycleCallbackManager ()

// 回调控制
@property (nonatomic, assign) BOOL callbackHandlingPaused;
@property (nonatomic, strong) NSMutableArray<DMPendingCallback *> *pendingCallbacks;

// 统计信息
@property (nonatomic, strong) DMCallbackStatistics *statistics;
@property (nonatomic, strong) NSMutableArray<DMCallbackLogItem *> *callbackLog;
@property (nonatomic, assign) NSUInteger maxLogCount;

// 错误处理
@property (nonatomic, copy, nullable) DMCallbackErrorHandler errorHandler;

// 线程安全
@property (nonatomic, strong) dispatch_queue_t callbackQueue;
@property (nonatomic, strong) dispatch_queue_t statisticsQueue;
@property (nonatomic, strong) dispatch_group_t callbackGroup;

@end

@implementation DMLifecycleCallbackManager

static DMLifecycleCallbackManager *_sharedManager = nil;
static dispatch_once_t onceToken;

#pragma mark - 单例实现

+ (instancetype)sharedManager {
    dispatch_once(&onceToken, ^{
        _sharedManager = [[self alloc] init];
    });
    return _sharedManager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setupCallbackManager];
    }
    return self;
}

- (void)setupCallbackManager {
    // 创建队列
    _callbackQueue = dispatch_queue_create("com.dualmediationsdk.callback.manager", DISPATCH_QUEUE_CONCURRENT);
    _statisticsQueue = dispatch_queue_create("com.dualmediationsdk.callback.statistics", DISPATCH_QUEUE_SERIAL);
    _callbackGroup = dispatch_group_create();
    
    // 初始化配置
    _asyncCallbackEnabled = YES;
    _callbackTimeout = 10.0;
    _statisticsEnabled = NO;
    _debugModeEnabled = NO;
    _callbackHandlingPaused = NO;
    
    // 初始化容器
    _pendingCallbacks = [NSMutableArray array];
    _statistics = [[DMCallbackStatistics alloc] init];
    _callbackLog = [NSMutableArray array];
    _maxLogCount = 500;
}

#pragma mark - Facebook登录回调

- (DMCallbackHandleResult)handleFacebookLoginResult:(DMLoginResponse *)result {
    return [self handleGenericCallback:@"FacebookLogin" data:result];
}

- (void)handleFacebookLoginResultAsync:(DMLoginResponse *)result 
                            completion:(nullable void(^)(DMCallbackHandleResult result))completion {
    [self handleGenericCallbackAsync:@"FacebookLogin" data:result completion:completion];
}

#pragma mark - 产品相关回调

- (DMCallbackHandleResult)handleGetProductsResult:(NSArray<DMProductInfo *> *)products {
    return [self handleGenericCallback:@"GetProducts" data:products];
}

- (DMCallbackHandleResult)handleGetPurchasedProductsResult:(NSArray<DMPurchaseInfo *> *)purchases {
    return [self handleGenericCallback:@"GetPurchasedProducts" data:purchases];
}

- (DMCallbackHandleResult)handlePurchaseFailure:(NSError *)error productId:(NSString *)productId {
    NSDictionary *data = @{
        @"error": error,
        @"productId": productId ?: @""
    };
    return [self handleGenericCallback:@"PurchaseFailure" data:data];
}

- (DMCallbackHandleResult)handlePurchaseSuccess:(DMPurchaseInfo *)purchaseInfo {
    return [self handleGenericCallback:@"PurchaseSuccess" data:purchaseInfo];
}

- (DMCallbackHandleResult)handleRatingTriggerFailure:(NSError *)error {
    return [self handleGenericCallback:@"RatingTriggerFailure" data:error];
}

#pragma mark - 分享回调

- (DMCallbackHandleResult)handleShareResult:(BOOL)success 
                                      error:(nullable NSError *)error 
                                   platform:(NSString *)platform {
    NSDictionary *data = @{
        @"success": @(success),
        @"error": error ?: [NSNull null],
        @"platform": platform ?: @""
    };
    return [self handleGenericCallback:@"ShareResult" data:data];
}

#pragma mark - BMS配置回调

- (DMCallbackHandleResult)handleBMSConfigUpdate:(NSDictionary *)config {
    return [self handleGenericCallback:@"BMSConfigUpdate" data:config];
}

#pragma mark - 推送消息回调

- (DMCallbackHandleResult)handlePushMessageClick:(NSDictionary *)messageInfo {
    return [self handleGenericCallback:@"PushMessageClick" data:messageInfo];
}

- (void)triggerPushMessageClick:(NSString *)messageId {
    if (!messageId || messageId.length == 0) {
        [self logDebug:@"triggerPushMessageClick called with empty messageId"];
        return;
    }
    
    [self logDebug:@"Triggering push message click for messageId: %@", messageId];
    [self handleGenericCallback:@"PushMessageClick" data:messageId];
}

- (void)triggerPurchaseResult:(NSInteger)resultCode data:(nullable id)data {
    [self logDebug:@"Triggering purchase result with code: %ld", (long)resultCode];
    
    NSString *callbackType;
    if (resultCode == 0) {
        // 成功
        callbackType = @"PurchaseSuccess";
    } else {
        // 失败
        callbackType = @"PurchaseFailure";
    }
    
    [self handleGenericCallback:callbackType data:data];
}

#pragma mark - 通用回调处理

- (DMCallbackHandleResult)handleGenericCallback:(NSString *)callbackType data:(nullable id)data {
    if (self.callbackHandlingPaused) {
        [self logDebug:@"Callback handling paused, queuing callback: %@", callbackType];
        [self queuePendingCallback:callbackType data:data completion:nil];
        return DMCallbackHandleResultSuccess;
    }
    
    NSDate *startTime = [NSDate date];
    DMCallbackLogItem *logItem = [self createLogItemForCallback:callbackType timestamp:startTime];
    logItem.data = data;
    
    // 获取相应的回调处理器
    NSArray<id<DMSDKLifecycleDelegate>> *handlers = [[DMLifecycleDelegateRegistry sharedRegistry] getAllSDKCallbackDelegates];
    
    if (handlers.count == 0) {
        logItem.result = DMCallbackHandleResultNoHandlers;
        logItem.duration = [[NSDate date] timeIntervalSinceDate:startTime];
        [self addLogItem:logItem];
        return DMCallbackHandleResultNoHandlers;
    }
    
    logItem.handlerCount = handlers.count;
    
    // 分发回调
    DMCallbackHandleResult result = [self performCallbackDispatch:handlers 
                                                      callbackType:callbackType 
                                                              data:data];
    
    // 更新日志和统计
    logItem.result = result;
    logItem.duration = [[NSDate date] timeIntervalSinceDate:startTime];
    [self addLogItem:logItem];
    [self updateStatistics:result duration:logItem.duration];
    
    return result;
}

- (void)handleGenericCallbackAsync:(NSString *)callbackType 
                              data:(nullable id)data 
                        completion:(nullable void(^)(DMCallbackHandleResult result))completion {
    if (!self.asyncCallbackEnabled) {
        DMCallbackHandleResult result = [self handleGenericCallback:callbackType data:data];
        if (completion) {
            completion(result);
        }
        return;
    }
    
    dispatch_group_enter(self.callbackGroup);
    
    dispatch_async(self.callbackQueue, ^{
        DMCallbackHandleResult result = [self handleGenericCallback:callbackType data:data];
        
        dispatch_group_leave(self.callbackGroup);
        
        if (completion) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(result);
            });
        }
    });
}

#pragma mark - 回调分发核心逻辑

- (DMCallbackHandleResult)performCallbackDispatch:(NSArray<id<DMSDKLifecycleDelegate>> *)handlers 
                                      callbackType:(NSString *)callbackType 
                                              data:(nullable id)data {
    NSUInteger successCount = 0;
    NSUInteger failureCount = 0;
    
    for (id<DMSDKLifecycleDelegate> handler in handlers) {
        BOOL success = [self dispatchToHandler:handler callbackType:callbackType data:data];
        if (success) {
            successCount++;
        } else {
            failureCount++;
        }
    }
    
    return [self determineCallbackResult:successCount failureCount:failureCount totalCount:handlers.count];
}

- (BOOL)dispatchToHandler:(id<DMSDKLifecycleDelegate>)handler 
             callbackType:(NSString *)callbackType 
                     data:(nullable id)data {
    @try {
        // 根据回调类型调用相应的方法
        if ([callbackType isEqualToString:@"FacebookLogin"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnFbSuccess:)]) {
                [handler dmSDKOnFbSuccess:(DMLoginResponse *)data];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"GetProducts"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnProductsFetched:)]) {
                [handler dmSDKOnProductsFetched:(NSArray<DMProductInfo *> *)data];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"GetPurchasedProducts"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnPurchasedProductsFetched:purchaseList:)]) {
                // 需要传递产品类型参数，这里使用默认值
                [handler dmSDKOnPurchasedProductsFetched:DMProductTypeConsumable purchaseList:(NSArray<DMPurchaseInfo *> *)data];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"PurchaseFailure"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnPurchaseFail:code:type:message:)]) {
                NSDictionary *dict = (NSDictionary *)data;
                NSError *error = dict[@"error"];
                [handler dmSDKOnPurchaseFail:dict[@"productId"] 
                                        code:error.code 
                                        type:@"purchase_error" 
                                     message:error.localizedDescription];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"PurchaseSuccess"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnPurchaseSuccess:)]) {
                [handler dmSDKOnPurchaseSuccess:(DMPurchaseInfo *)data];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"RatingTriggerFailure"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnReviewTriggerFail:)]) {
                NSError *error = (NSError *)data;
                [handler dmSDKOnReviewTriggerFail:error.localizedDescription];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"ShareResult"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnShareCallBack:message:)]) {
                NSDictionary *dict = (NSDictionary *)data;
                NSString *message = dict[@"message"];
                [handler dmSDKOnShareCallBack:[dict[@"success"] boolValue] message:message];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"BMSConfigUpdate"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnBMSConfigCallBack:jsonString:)]) {
                NSDictionary *dict = (NSDictionary *)data;
                BOOL success = [dict[@"success"] boolValue];
                NSString *jsonString = dict[@"jsonString"];
                [handler dmSDKOnBMSConfigCallBack:success jsonString:jsonString];
                return YES;
            }
        } else if ([callbackType isEqualToString:@"PushMessageClick"]) {
            if ([handler respondsToSelector:@selector(dmSDKOnPushMessageClick:)]) {
                NSString *messageId = (NSString *)data;
                [handler dmSDKOnPushMessageClick:messageId];
                return YES;
            }
        }
        
        return NO; // 处理器不支持该回调类型
        
    } @catch (NSException *exception) {
        [self handleCallbackError:[NSError errorWithDomain:@"DMLifecycleCallbackManager" 
                                                      code:-1 
                                                  userInfo:@{NSLocalizedDescriptionKey: exception.reason ?: @"Unknown error"}]
                     callbackType:callbackType 
                             data:data];
        return NO;
    }
}

- (DMCallbackHandleResult)determineCallbackResult:(NSUInteger)successCount 
                                     failureCount:(NSUInteger)failureCount 
                                       totalCount:(NSUInteger)totalCount {
    if (totalCount == 0) {
        return DMCallbackHandleResultNoHandlers;
    }
    
    if (failureCount == 0) {
        return DMCallbackHandleResultSuccess;
    } else if (successCount > 0) {
        return DMCallbackHandleResultPartialFailure;
    } else {
        return DMCallbackHandleResultFailure;
    }
}

#pragma mark - 回调队列管理

- (void)pauseCallbackHandling {
    dispatch_barrier_async(self.callbackQueue, ^{
        self.callbackHandlingPaused = YES;
        [self logDebug:@"Callback handling paused"];
    });
}

- (void)resumeCallbackHandling {
    dispatch_barrier_async(self.callbackQueue, ^{
        self.callbackHandlingPaused = NO;
        [self logDebug:@"Callback handling resumed"];
        
        // 处理待处理的回调
        [self processPendingCallbacks];
    });
}

- (BOOL)isCallbackHandlingPaused {
    __block BOOL paused = NO;
    dispatch_sync(self.callbackQueue, ^{
        paused = self.callbackHandlingPaused;
    });
    return paused;
}

- (void)clearPendingCallbacks {
    dispatch_barrier_async(self.callbackQueue, ^{
        [self.pendingCallbacks removeAllObjects];
        [self logDebug:@"Cleared all pending callbacks"];
    });
}

- (NSUInteger)getPendingCallbackCount {
    __block NSUInteger count = 0;
    dispatch_sync(self.callbackQueue, ^{
        count = self.pendingCallbacks.count;
    });
    return count;
}

- (void)queuePendingCallback:(NSString *)callbackType data:(nullable id)data completion:(nullable void(^)(DMCallbackHandleResult result))completion {
    dispatch_barrier_async(self.callbackQueue, ^{
        DMPendingCallback *pendingCallback = [[DMPendingCallback alloc] init];
        pendingCallback.callbackType = callbackType;
        pendingCallback.data = data;
        pendingCallback.timestamp = [NSDate date];
        pendingCallback.completion = completion;
        
        [self.pendingCallbacks addObject:pendingCallback];
    });
}

- (void)processPendingCallbacks {
    NSArray<DMPendingCallback *> *callbacks = [self.pendingCallbacks copy];
    [self.pendingCallbacks removeAllObjects];
    
    for (DMPendingCallback *callback in callbacks) {
        DMCallbackHandleResult result = [self handleGenericCallback:callback.callbackType data:callback.data];
        
        if (callback.completion) {
            dispatch_async(dispatch_get_main_queue(), ^{
                callback.completion(result);
            });
        }
    }
    
    [self logDebug:@"Processed %lu pending callbacks", (unsigned long)callbacks.count];
}

#pragma mark - 错误处理

- (void)setCallbackErrorHandler:(nullable DMCallbackErrorHandler)errorHandler {
    self.errorHandler = errorHandler;
}

- (void)handleCallbackError:(NSError *)error callbackType:(NSString *)callbackType data:(nullable id)data {
    [self logDebug:@"Callback error for type %@: %@", callbackType, error.localizedDescription];
    
    if (self.errorHandler) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.errorHandler(error, callbackType, data);
        });
    }
}

#pragma mark - 统计和日志

- (void)updateStatistics:(DMCallbackHandleResult)result duration:(NSTimeInterval)duration {
    if (!self.statisticsEnabled) {
        return;
    }
    
    dispatch_async(self.statisticsQueue, ^{
        self.statistics.totalCallbacks++;
        self.statistics.totalProcessTime += duration;
        
        if (result == DMCallbackHandleResultSuccess || result == DMCallbackHandleResultPartialFailure) {
            self.statistics.successfulCallbacks++;
        } else {
            self.statistics.failedCallbacks++;
        }
    });
}

- (DMCallbackLogItem *)createLogItemForCallback:(NSString *)callbackType timestamp:(NSDate *)timestamp {
    DMCallbackLogItem *item = [[DMCallbackLogItem alloc] init];
    item.callbackType = callbackType;
    item.timestamp = timestamp;
    return item;
}

- (void)addLogItem:(DMCallbackLogItem *)logItem {
    if (!self.debugModeEnabled) {
        return;
    }
    
    dispatch_async(self.statisticsQueue, ^{
        [self.callbackLog addObject:logItem];
        
        // 限制日志数量
        while (self.callbackLog.count > self.maxLogCount) {
            [self.callbackLog removeObjectAtIndex:0];
        }
    });
}

- (nullable DMCallbackStatistics *)getCallbackStatistics {
    if (!self.statisticsEnabled) {
        return nil;
    }
    
    __block DMCallbackStatistics *stats = nil;
    dispatch_sync(self.statisticsQueue, ^{
        stats = [self.statistics copy];
    });
    return stats;
}

- (void)resetCallbackStatistics {
    dispatch_async(self.statisticsQueue, ^{
        self.statistics = [[DMCallbackStatistics alloc] init];
    });
}

- (NSDictionary *)getPerformanceReport {
    __block NSDictionary *report = nil;
    dispatch_sync(self.statisticsQueue, ^{
        report = @{
            @"totalCallbacks": @(self.statistics.totalCallbacks),
            @"successfulCallbacks": @(self.statistics.successfulCallbacks),
            @"failedCallbacks": @(self.statistics.failedCallbacks),
            @"averageProcessTime": @(self.statistics.averageProcessTime),
            @"totalProcessTime": @(self.statistics.totalProcessTime),
            @"pendingCallbacks": @([self getPendingCallbackCount]),
            @"callbackHandlingPaused": @(self.callbackHandlingPaused),
            @"asyncCallbackEnabled": @(self.asyncCallbackEnabled)
        };
    });
    return report;
}

- (NSArray *)getCallbackHistory:(NSUInteger)limit {
    __block NSArray *history = nil;
    
    dispatch_sync(self.statisticsQueue, ^{
        if (limit == 0 || limit >= self.callbackLog.count) {
            history = [self.callbackLog copy];
        } else {
            NSRange range = NSMakeRange(self.callbackLog.count - limit, limit);
            history = [self.callbackLog subarrayWithRange:range];
        }
        
        // 按时间倒序排列
        history = [history sortedArrayUsingComparator:^NSComparisonResult(DMCallbackLogItem *obj1, DMCallbackLogItem *obj2) {
            return [obj2.timestamp compare:obj1.timestamp];
        }];
    });
    
    return history;
}

#pragma mark - 调试支持

- (NSDictionary *)getDebugInfo {
    return @{
        @"callbackHandlingPaused": @(self.callbackHandlingPaused),
        @"asyncCallbackEnabled": @(self.asyncCallbackEnabled),
        @"statisticsEnabled": @(self.statisticsEnabled),
        @"debugModeEnabled": @(self.debugModeEnabled),
        @"callbackTimeout": @(self.callbackTimeout),
        @"pendingCallbacks": @([self getPendingCallbackCount]),
        @"logCount": @(self.callbackLog.count),
        @"maxLogCount": @(self.maxLogCount)
    };
}

- (BOOL)validateManagerState {
    // 验证配置参数
    if (self.callbackTimeout <= 0) {
        [self logDebug:@"Invalid callback timeout: %f", self.callbackTimeout];
        return NO;
    }
    
    // 验证队列状态
    if (!self.callbackQueue || !self.statisticsQueue || !self.callbackGroup) {
        [self logDebug:@"Missing required callback queues or group"];
        return NO;
    }
    
    return YES;
}

- (nullable NSString *)exportCallbackLogWithLimit:(NSUInteger)limit {
    __block NSString *jsonString = nil;
    
    dispatch_sync(self.statisticsQueue, ^{
        NSArray *logsToExport = self.callbackLog;
        if (limit > 0 && limit < logsToExport.count) {
            NSRange range = NSMakeRange(logsToExport.count - limit, limit);
            logsToExport = [logsToExport subarrayWithRange:range];
        }
        
        NSMutableArray *logArray = [NSMutableArray array];
        for (DMCallbackLogItem *item in logsToExport) {
            NSDictionary *logDict = @{
                @"callbackType": item.callbackType,
                @"timestamp": @([item.timestamp timeIntervalSince1970]),
                @"result": @(item.result),
                @"duration": @(item.duration),
                @"handlerCount": @(item.handlerCount),
                @"error": item.errorDescription ?: [NSNull null],
                @"hasData": @(item.data != nil)
            };
            [logArray addObject:logDict];
        }
        
        NSDictionary *exportData = @{
            @"exportTime": @([[NSDate date] timeIntervalSince1970]),
            @"logCount": @(logArray.count),
            @"logs": logArray
        };
        
        NSError *error = nil;
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:exportData
                                                           options:NSJSONWritingPrettyPrinted
                                                             error:&error];
        
        if (jsonData && !error) {
            jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        } else {
            [self logDebug:@"Failed to export callback log as JSON: %@", error.localizedDescription];
        }
    });
    
    return jsonString;
}

- (DMCallbackHandleResult)simulateCallback:(NSString *)callbackType data:(nullable id)data {
    [self logDebug:@"Simulating callback: %@", callbackType];
    return [self handleGenericCallback:callbackType data:data];
}

- (void)logDebug:(NSString *)format, ... {
    if (!self.debugModeEnabled) {
        return;
    }
    
    va_list args;
    va_start(args, format);
    NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
    va_end(args);
    
    NSLog(@"[DMLifecycleCallbackManager] %@", message);
}

@end